feat: ScenarioBranch facade + LF integration mapping v1 - #265
Conversation
…enario-world agent
Three additive changes that compose existing pieces (Pearl Rung 3
intervention, Lance versioning, archetype meta-state, WorldModelDto)
into a first-class explicit scenario branching surface.
contract/scenario.rs (NEW, ~340 LOC including tests):
ScenarioBranch — named handle with parent_tag, fork_seed,
archetype_prior, intervention list, default NARS inference mode.
ScenarioDiff — three-resolution gestalt diff (graph / fingerprint /
world-model). Composes VersionedGraph::diff + worlds_differ +
WorldModelDto.field_state.dissonance.
ScenarioWorld trait — fork / simulate_forward / forecast_palette /
diff_branches / replay. Zero-dep; concrete impls live downstream.
7 unit tests, all pass.
archetype/world.rs (WIRE, was Unimplemented):
fork(branch) — appends ?branch=<name> URI suffix, resets tick.
Empty branch name → InvalidBranch.
at_tick(tick) — clones with rewound tick, validates tick <= current,
InvalidTick if requested > current.
Archetype crate stays lance-free per ADR-0001; downstream resolver
translates URI suffix → VersionedGraph::tag_version + new dataset
path.
6 new tests, 16 total pass.
archetype/error.rs (EXTEND):
+ InvalidBranch
+ InvalidTick { requested, current }
.claude/agents/scenario-world.md (NEW):
Specialist agent with the full decision tree:
- Time travel vs branching vs intervention (three operations,
not one).
- Why scenario_id column was rejected (5 reasons including
I-VSA-IDENTITIES violation).
- Why a separate scenarios crate was rejected.
- Why URI-suffix branching (keeps archetype lance-free).
- Why CounterfactualSynthesis as default inference mode.
- Why fork_seed (Apache-Temporal-extracted determinism).
- Why palette compose-chain forecast (Chronos-extracted method).
- Why three-resolution diff (gestalt structure preservation).
LF-80/81 reframing: marketplace = portable auditable counterfactuals,
not speculative bundle distribution. Becomes enterprise anchor
product when ScenarioBundle = Ontology + ScenarioBranch set +
ModelBinding + AuditEntry chain + spider-rs evidence URLs.
docs/ScenarioWorldCounterfactual.md (NEW):
Cross-cutting design doc with TL;DR, decision summary table, tools
considered (NARS / Archetype / ONNX / Chronos / Apache Temporal)
and what each contributed, three-resolution diff explanation, and
the LF-80/81 reframing for regulated industries.
240 contract + 16 archetype tests pass. Workspace cargo check clean.
https://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh
Comprehensive map of all 41 LF + 4 W chunks shipped or queued across
the lance-graph workspace. Producer-side mirror of SMB session's
foundry-parity-checklist.md; lives in lance-graph so future producer
sessions see the state at a glance.
Status totals:
17 DONE (Tier 1 LF-1..8 + W-1..4 + LF-21/22/90/91/92)
2 IN-PR (LF-70, LF-72 on this branch via ScenarioBranch facade)
22 QUEUED (Stage 1 connectors, Stage 2 ontology adds, Stage 3 storage,
Stage 4 search, Stage 5 models, Stage 6 decisions,
Stage 7 LF-73/74/75 forward-sim wiring)
2 DEFERRED (LF-32 sharded writes, LF-53 AIP Logic UI)
2 FUTURE (LF-80/81 marketplace bundles)
Stage 7 redesign documented:
LF-71 (scenario_id column) DROPPED — would widen SIMD sweep + duplicate
Lance versioning. Replaced with role-bind + dataset-path branch identity.
LF-73 simulate_forward — wires existing dormant CounterfactualSynthesis
NARS inference type into ScenarioWorld trait.
LF-74 forecast_palette — Chronos-extracted method (compose-chain over
existing 256-archetype palette + ComposeTable). Adopt the idea,
don't pull in the model.
LF-75 replay — Apache-Temporal-extracted method (deterministic replay
via captured fork_seed). Adopt the idea, don't adopt durable-execution
workflow runtime.
Sequencing recommendation for next 10 chunks ordered by leverage:
1. Merge this branch (Stage 7 + scenario-world agent)
2. LF-12 Pipeline DAG (unblocks Stage 1 connector tier)
3. LF-50/52 ModelRegistry + LlmProvider (xAI/OpenAI/Anthropic/Ollama)
4. LF-20 FunctionSpec
5. LF-23 NotificationSpec
6. LF-31 scan_as_of (almost-free trait expose of existing VersionedGraph)
7. LF-10 Connector registry
8. LF-61 NARS-revision-on-correction
9. LF-73 simulate_forward
10. LF-40 Tantivy full-text search
INTEGRATION_PLANS.md prepended with new v1 entry per board hygiene rule.
https://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0289567a11
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let separator = if self.dataset_uri.contains('?') { "&" } else { "?" }; | ||
| Ok(World { | ||
| tick: 0, | ||
| dataset_uri: format!("{}{}branch={}", self.dataset_uri, separator, branch), |
There was a problem hiding this comment.
Percent-encode branch names in forked dataset URI
The branch name is interpolated directly into the query string, so names containing reserved characters (for example &, #, or spaces) produce an ambiguous or malformed URI and can resolve to the wrong branch downstream (e.g., branch=a&b is parsed as branch=a). Since fork accepts arbitrary non-empty branch names, this can silently misroute scenario writes/reads in real workloads where names come from user-defined scenario labels; the branch value should be URL-encoded (or stored separately from URI text) before concatenation.
Useful? React with 👍 / 👎.
Follow-up to the toolchain commit on this branch, from the same measurement.
No workflow here runs `--workspace` or `--all`; every gate names one crate by
path. So `[workspace] members` gates nothing, and ELEVEN of 25 members were in
no job. Two of them (catalog, planner) are deps of lance-graph, so their libs
compiled inside a gated build while their tests ran nowhere; the rest compiled
nowhere at all. That is how `lance-graph-hydrate` reached `main` un-compiling —
`object_store 0.13.2`, a semver-compatible release already in the lockfile,
moved `get`/`put` onto `ObjectStoreExt`, and nothing could see it.
Every step added here was RUN LOCALLY on the pinned 1.97.1 first, and the count
in each comment is what it returned. Nothing is armed on hope:
catalog 12+15 · planner 368+4 · ontology 276+2+6 · rbac 23 · archetype 16
consumer-conformance 8 · sigma-tier-router 20 · neural-debug 11
cognitive-shader-driver 107+2 · hydrate 33
`lance-graph-benches` gets `cargo check --benches` instead of `cargo test`: it
is a benches-only crate with one `harness = false` target, so `cargo test` runs
zero tests and would be a gate that cannot fail. Same shape build.yml already
uses for lance-graph's own benches.
Formatting gates for the same ten. Nine were already rustfmt-clean and simply
had nothing holding them there; `sigma-tier-router` was NOT — 14 hunks in one
file, formatted here, rustfmt output only, its 20 tests unchanged.
Two things this deliberately does NOT do:
- No clippy gates for these crates. Not measured crate-by-crate, and
`causal-edge` alone already carries 7 pre-existing findings
(ISS-CAUSAL-EDGE-CARRIES-SEVEN-PRE-EXISTING-CLIPPY-FINDINGS). Arming a lint
gate on unmeasured crates fails PRs for defects they did not introduce.
- No `--workspace` job. That would catch every FUTURE member automatically and
is the better long-run answer, but it is a scope and cost decision, not a
repair. This closes the measured gap; the standing choice stays open.
Also here, because a PR that adds a gate must leave CI green: the two-line
`ObjectStoreExt` import that makes `lance-graph-hydrate` compile, its rustfmt
pass (4 files), and its live `trim_split_whitespace` clippy warning. Those same
fixes ride with the crate's own PR (claude/hydrate-from-zip) — identical hunks,
so a rebase after this merges drops them cleanly. Without them the hydrate gate
added here would be red on arrival.
Cargo.lock is NOT in this commit. It gained one line (`blake3`) from advancing
the OGAR sibling checkout #265 → #279, which is a deliberate dependency bump
and not part of a CI change.
Verified: all seven workflows parse under `yaml.safe_load`, and every one of
the 25 workspace members now resolves to at least one job.
Background: EPIPHANIES E-THE-GATE-IS-A-HAND-MAINTAINED-ALLOWLIST-NOT-THE-WORKSPACE-1
and ISSUES ISS-CI-GATE-IS-AN-ALLOWLIST-NINE-MEMBERS-UNGATED, both landing with
claude/hydrate-from-zip.
Summary
contract::scenario(~340 LOC, 7 tests) — named handle composing Pearl Rung 3 intervention, Lance versioning, archetype meta-state, and WorldModelDto gestalt into explicit counterfactual branchingarchetype::World::fork/at_tickfromUnimplementedstubs to working implementations (URI-suffix branching + tick rewind validation)Stage 7 redesign (LF-70/71/72)
World::forkfull implarchetype::World::fork+ScenarioBranch::newwith fork_seed, archetype_prior, interventionsscenario_idcolumn on every BindSpace SoA rowdiff(base, fork)ScenarioDiffcomposing three resolutions: graph-node + fingerprint-Hamming + gestalt-dissonanceNew chunks added (LF-73/74/75 — queued, not implemented)
simulate_forward— wires dormantNarsInference::CounterfactualSynthesisforecast_palette— Chronos-extracted compose-chain method over existing 256-archetype palettereplay— Apache-Temporal-extracted deterministic replay via fork_seedTest plan
cargo test -p lance-graph-contract --lib scenario— 7 passedcargo test --manifest-path crates/lance-graph-archetype/Cargo.toml --lib— 16 passedcargo clippy -p lance-graph-contract -p lance-graph-archetype— clean on new filescargo check— full workspace cleanhttps://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh
Generated by Claude Code